home *** CD-ROM | disk | FTP | other *** search
- /* DEBUG.C
- ************************************************************************
- * *
- * PC Scheme/Geneva 4.00 Borland C code *
- * *
- * (c) 1985-1988 by Texas Instruments, Inc. See COPYRIGHT.TXT *
- * (c) 1992 by L. Bartholdi & M. Vuilleumier, University of Geneva *
- * *
- *----------------------------------------------------------------------*
- * *
- * Main Debugger Code *
- * *
- *----------------------------------------------------------------------*
- * *
- * Created by: John Jensen Date: 1985 *
- * Revision history: *
- * - 18 Jun 92: Renaissance (Borland Compilers, ...) *
- * *
- * ``In nomine omnipotentii dei'' *
- ************************************************************************/
-
- #include <stdio.h>
- #include <conio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include "scheme.h"
-
- #ifndef BUFSIZE
- #define BUFSIZE 160
- #endif
- #define INTR_OUTPUT if (GETCHready()) {(void) GETCH(); break;}
-
- int check_page(char [], unsigned *, unsigned *, unsigned *);
- int get_hex(char);
- unsigned hex_val(char [], unsigned *);
- int get_int(char);
- unsigned int_val(char [], unsigned *);
- int hex_byte(char [], unsigned *);
- long hex_word(char [], unsigned *);
-
- void dump_scheme( unsigned, unsigned, unsigned, unsigned, void (*)( SCHEMEOBJ, unsigned, unsigned, unsigned ) );
- void dump_list( unsigned, unsigned, unsigned );
- int dump_environment(unsigned, unsigned);
- void dump_hash(void);
- void dump_hex(unsigned, unsigned, unsigned);
- void dump_memory(unsigned, unsigned, unsigned);
- void dump_page_table(void);
- void dump_prop(void);
- void dump_regs(void);
- void dump_stk(void);
- void prt_reg(int);
- void annotate(unsigned, unsigned);
-
- unsigned char get_b(unsigned);
- unsigned get_reg(unsigned);
- unsigned get_w(unsigned);
- void save_regs( unsigned *, int );
-
- char *spchars[SPECIALCHARS] = {
- "\nNEWLINE", " SPACE", "\177RUBOUT", "\fPAGE",
- "\tTAB", "\bBACKSPACE", "\rRETURN", "\033ESCAPE"};
-
- #define NUMREGS 7 /* no instruction has more than that ! */
- #define NOTUSED 0xffff
- typedef enum { /* Format Codes: */
- NOP, /* no operands */
- R, /* reg */
- RR, /* reg,reg */
- RRR, /* reg,reg,reg */
-
- C, /* short offset (signed) */
- B, /* short offset (unsigned) */
- I, /* long offset (signed) */
-
- BR, /* byte (unsigned),reg */
-
- RC, /* reg,short offset (signed) */
- RB, /* reg,short offset (unsigned) */
- RI, /* reg,long offset (signed) */
-
- RBR, /* reg,byte (unsigned),reg */
- RRC, /* reg,reg,byte */
- RUR, /* reg,word (unsigned),reg */
- RRI, /* reg,reg,word */
-
- RBC, /* reg,byte (unsigned),byte (signed) */
- RIB, /* reg,word (signed),byte (unsigned) */
- ICB, /* word (signed),byte (signed),byte (unsigned) */
-
- R4, /* reg,reg,reg,reg */
- R5, /* reg,reg,reg,reg,reg */
- R6, /* reg,reg,reg,reg,reg,reg */
- R7, /* reg,reg,reg,reg,reg,reg,reg */
-
- BRV, /* length, reg, zero or more regs */
- NUMMODES }
- ADDRESSINGMODES;
-
- static int n_ops[NUMMODES] = {
- 0, 1, 2, 3,
- -1, -1, -1,
- -1,
- 2, -1, -1,
- -1, -1,
- -1, -1, -1,
- 4, 5, 6, 7,
- -1};
-
- static char format[0x100] = {
- /* 000 */ RR, RB, RC, R, RB, RBC, RB, RB,
- /* 008 */ RB, RB, RI,/*!*/RR, RB, RBC, RB, RB,
- /* 016 */ RB, RBR, RUR, RRR, RR, RR, RR, RR,
- /* 024 */ R, R, B, RR, NOP, BR, B, RB,
- /* 032 */ C, I, RC, RI, RC, RI, RC, RI,
- /* 040 */ RC, RI, RRC, RRI, RRC, RRI, R, R,
- /* 048 */ ICB, ICB, ICB, ICB, RB, RB, R, R,
- /* 056 */ RR, RR, R, NOP, RIB, B, R, RR,
- /* 064 */ RR, RR, RR, RR, RR, RR, RR, RR,
- /* 072 */ RR, RR, RR, RR, RR, RR, RR, RRR,
- /* 080 */ RR, RC, RR, RR, RC, RR, RC, RR,
- /* 088 */ RR, R, R, R, RR, RR, RR, RR,
- /* 096 */ RR, RR, RR, RR, RR, RR, RR, RR,
- /* 104 */ RR, RR, R, R, RR, RR, RR, R,
- /* 112 */ RR, RR, RR, RR, RR, RRR, R, RR,
- /* 120 */ RR, RR, RR, NOP, NOP, RR, RR, RR,
-
- /* 128 */ R, R, R, R, R, R, R, R,
- /* 136 */ R, R, R, R, R, R, R, R,
- /* 144 */ R, R, R, R, R, R, R, R,
- /* 152 */ R, R, R, R, R, R, NOP, NOP,
- /* 160 */ R, R, R6, NOP, NOP, R, R, RRR,
- /* 168 */ R, R, RR, RRR, R5, R, R, R,
- /* 176 */ RR, R, RR, RR, RR, R, R, R,
- /* 184 */ R, NOP, R, R, R, R, R, R,
- /* 192 */ RR, RR, RR, RR, R, R, R, RR,
- /* 200 */ RRR, RR, RR, R, R, R, R4, R4,
- /* 208 */ R, RRR, RR, R, R, RR, R7, BRV,
- /* 216 */ RR, R, R, RR, RRR, B, B, RB,
- /* 224 */ RB, R, RRR, R, R, R, RR, RRR,
- /* 232 */ BRV, BRV, NOP, NOP, NOP, NOP, NOP, NOP,
- /* 240 */ RR, RR, RRR, R, R, R, R, NOP,
- /* 248 */ NOP, NOP, R, NOP, NOP, NOP, NOP, NOP};
-
- /************************************************************************/
- /* "Disassemble" a Scheme Instruction for Error Message *IRRITANT* */
- /* */
- /* Note: This routine works for instructions with only registers for */
- /* operands. Immediates, offsets, etc., will cause a list to */
- /* be created with only the function name in the first position. */
- /* */
- /* The "offset" operand is the absolute displacement of the */
- /* instruction in the page containing the current code block, */
- /* not the displacement relative to the beginning of the code */
- /* block. */
- /************************************************************************/
- void disassemble(char *function, unsigned offset)
- {
- REGPTR reg_addr[10]; /* register addresses of the instruction's operands */
- unsigned page;
- int i;
- int numoperands;
- int op;
- REG fix_reg = FIXNUM(0);
-
- /* determine characteristics of the instruction with which we're dealing */
- page = CORRPAGE(cb_reg.page);
- op = get_byte(page, offset++);
- tmp_reg = nil_reg;
- if ((numoperands = n_ops[format[op]]) > 0)
- {
- /* compute the register address for each operand */
- for (i = 0; i < numoperands; i++)
- reg_addr[i] = regs + get_byte(page, offset++) / sizeof(REG);
- /* if last operand is an immediate operand, phoney up a register for it */
- if (format[op] == RC)
- {
- reg_addr[i - 1] = &fix_reg;
- fix_reg.disp = ((signed)get_byte(page, offset - 1) << 8) >> 8;
- }
- /* cons up argument list */
- for (i = numoperands - 1; i >= 0; i--)
- cons(&tmp_reg, reg_addr[i], &tmp_reg);
- }
- /* create a symbol for the function name and cons on front of argument list */
- intern(&tm2_reg, function, strlen(function));
- cons(&tmp_reg, &tm2_reg, &tmp_reg);
- }
-
- #ifdef VMDEBUG /* cancel module if no debug */
-
- static char *page_type[NUMTYPES] = {"LIST", "FIX", "FLO", "BIG", "SYM",
- "STR", "ARY", "CONT", "CLOS", "FREE",
- "CODE", "I86", "PORT", "CHAR", "ENV"};
-
- unsigned long icount[0x100] = { 0, };
-
- static char *opcodes[0x100] = {
- /* 000 */ "load", "ld-const", "ld-imm", "ld-nil", "ld-local", "ld-lex", "ld-env", "ld-global",
- /* 008 */ "ld-fluid", "ld-vec-s", "ld-vec-l", "ld-vec-r", "st-local", "st-lex", "st-env", "st-global",
- /* 016 */ "st-fluid", "st-vec-s", "st-vec-l", "st-vec-r", "set-car!", "set-cdr!", "set-ref!", "Iap-ref!",
- /* 024 */ "pop", "push", "drop", "ld-global-r", "(unused)", "bind-fl", "unbind-fl", "define!",
- /* 032 */ "jmp-s", "jmp-l", "j-nil-s", "j-nil-l", "jnnil-s", "jnnil-l", "jatom-s", "jatom-l",
- /* 040 */ "jnatom-s", "jnatom-l", "jeq-s", "jeq-l", "jneq-s", "jneq-l", "deref", "ref",
- /* 048 */ "call", "call-tr", "call/cc", "call/cc-tr", "call-cl", "call-cl-tr", "call/cc-cl", "call/cc-cl-tr",
- /* 056 */ "apply-cl", "apply-cl-tr", "execute", "exit", "close", "drop-env", "mk-hash-env", "ld-fluid-r",
- /* 064 */ "%%car", "%%cdr", "caar", "cadr", "cdar", "cddr", "caaar", "caadr",
- /* 072 */ "cadar", "caddr", "cdaar", "cdadr", "cddar", "cdddr", "cadddr", "cons",
- /* 080 */ "add", "add-imm", "sub", "mul", "mul-imm", "div", "div-imm", "quotient",
- /* 088 */ "remainder", "%car", "%cdr", "random", "<", "<=", "=", ">",
- /* 096 */ ">=", "!=", "max", "min", "eq?", "eqv?", "equal?", "memq",
- /* 104 */ "memv", "member", "reverse!", "reverse", "assq", "assv", "assoc", "list",
- /* 112 */ "append!", "append", "delq!", "delete!", "get-prop", "put-prop", "proplist", "remprop",
- /* 120 */ "list2", "list-ref", "list-tail", "(unused)", "(unused)", "bitwise-xor", "bitwise-and", "bitwise-or",
-
- /* 128 */ "atom?", "closure?", "code?", "continuation?","even?", "float?", "fluid-bound?", "integer?",
- /* 136 */ "null?", "number?", "odd?", "pair?", "port?", "proc?", "ref?", "string?",
- /* 144 */ "symbol?", "vector?", "zero?", "negative?", "positive?", "abs", "float", "minus",
- /* 152 */ "floor", "ceiling", "truncate", "round", "char?", "env?", "(unused)", "(unused)",
- /* 160 */ "ascii->char", "char->ascii", "%str-str", "(unused)", "(unused)", "length", "last-pair", "substr",
- /* 168 */ "alloc-vector", "vector-size", "vector-fill", "mk-pack-vector","substr-display","unread-char","%start-timer", "%stop-timer",
- /* 176 */ "open-port", "close-port", "prin1", "princ", "print", "newline", "%push-history","%get-history",
- /* 184 */ "print-length", "clear-history","read-line", "read-atom", "read-char", "%transcript", "read-char-ready?","fasl",
- /* 192 */ "char=", "char-equal?", "char<", "char-less?", "char-upcase", "char-downcase","string-length","string-ref",
- /* 200 */ "string-set!", "make-string", "string-fill!", "str->sym", "str->un-sym", "sym->str", "find-next-char","find-prev-char",
- /* 208 */ "%make-window", "%reify-port!", "%reify-port", "%clear-window","%save-window", "%restore-window","%str-append","%graphics",
- /* 216 */ "%reify", "mk-env", "env-parent", "env-lookup", "define-env", "push-env", "drop-env", "ld-env",
- /* 224 */ "st-env", "set-glob-env!","%reify!", "obj-hash", "obj-unhash", "%reify-stack", "%reify-stack!","set-file-position!",
- /* 232 */ "%esc", "%mouse", "(unused)", "(unused)", "(unused)", "(unused)", "(unused)", "(unused)",
- /* 240 */ "make-port", "%port-get-att","%port-set-att!","%read-char", "%read-line", "%char-ready?", "%peek-char", "%gc2",
- /* 248 */ "%halt", "%gc", "ptime", "reset", "scheme-reset", "clear-regs", "(escape)", "begin-debug"};
-
- static unsigned page, disp, displ;
-
- RETVALUE t_inst(unsigned _page, unsigned *pc, unsigned *retcode, int flags)
- {
- unsigned len = 3, op;
- RETVALUE stat = PROCEED;
- REG before[NUMREGS];
- unsigned reg[NUMREGS];
-
- disp = *pc;
- page = _page;
- displ = flags & T_DISPLAY;
-
- op = get_byte(page, disp);
- if (displ)
- zprintf("\t\t\t\t%3x:%04x %12s", page, *pc, opcodes[op]);
-
- for( int i = 0; i < NUMREGS; i++ )
- reg[i] = NOTUSED;
-
- switch (format[op]) {
- case NOP:
- if (displ)
- zprintf("\n");
- len = 1;
- break;
-
- case R: /* one register operand */
- save_regs( reg, 1 );
- fmt_regs(1);
- len = 2;
- break;
-
- case RR: /* two register operands */
- save_regs( reg, 2 );
- fmt_regs(2);
- break;
-
- case RRR: /* three register operands */
- save_regs( reg, 3 );
- fmt_regs(3);
- len = 4;
- break;
-
- case R4: /* four register operands */
- save_regs( reg, 4 );
- fmt_regs(4);
- len = 5;
- break;
-
- case R5: /* five register operands */
- save_regs( reg, 5 );
- fmt_regs(5);
- len = 6;
- break;
-
- case R6: /* six register operands */
- save_regs( reg, 6 );
- fmt_regs(6);
- len = 7;
- break;
-
- case R7: /* seven register operands */
- save_regs( reg, 7 );
- fmt_regs(7);
- len = 8;
- break;
-
- case C: /* short offset (signed byte) */
- if (displ)
- zprintf(" %d\n", (signed char) get_w(1));
- len = 2;
- break;
-
- case I: /* long offset (signed word) */
- if (displ)
- zprintf(" %d\n", (signed) get_w(1));
- break;
-
- case B: /* unsigned short offset (byte) */
- if (displ)
- zprintf(" %d\n", get_b(1));
- len = 2;
- break;
-
- case BR: /* unsigned short offset (byte) plus register */
- reg[0] = get_reg(2);
- if (displ)
- zprintf(" %d, R%d\n", get_b(1), reg[0]);
- break;
-
- case RC: /* one register plus short offset (signed) */
- save_regs( reg, 1 );
- if (displ)
- zprintf(" R%d, %d\n", reg[0], (signed char) get_b(2));
- break;
-
- case RB: /* one register plus short offset (unsigned) */
- save_regs( reg, 1 );
- if (displ)
- zprintf(" R%d, %d\n", reg[0], get_b(2));
- break;
-
- case RI: /* one register plus long offset (signed) */
- save_regs( reg, 1 );
- if (displ)
- zprintf(" R%d, %d\n", reg[0], (signed) get_w(2));
- len = 4;
- break;
-
- case RBR: /* register, short offset (unsigned), register */
- save_regs( reg, 1 );
- reg[1] = get_reg(3);
- if (displ)
- zprintf(" R%d, %d, R%d\n", reg[0], get_b(2), reg[1]);
- len = 4;
- break;
-
- case RRC: /* register, register, short offset (signed), register */
- save_regs( reg, 2 );
- if (displ)
- zprintf(" R%d, R%d, %d\n", reg[0], reg[1], (signed char) get_b(3) );
- len = 4;
- break;
-
- case RRI: /* register, register, short offset (signed), register */
- save_regs( reg, 2 );
- if (displ)
- zprintf(" R%d, R%d, %d\n", reg[0], reg[1], (signed) get_w(3) );
- len = 4;
- break;
-
- case RUR: /* register, long offset (unsigned), register */
- save_regs( reg, 1 );
- reg[1] = get_reg(4);
- if (displ)
- zprintf(" R%d, %d, R%d\n", reg[0], get_w(2), reg[1]);
- len = 5;
- break;
-
- case RBC: /* register, unsigned byte, signed byte */
- save_regs( reg, 1 );
- if (displ)
- zprintf(" R%d, %d, %d\n", reg[0], get_b(2), (signed char) get_b(3));
- len = 4;
- break;
-
- case RIB: /* register, signed word, unsigned byte */
- save_regs( reg, 1 );
- if (displ)
- zprintf(" R%d, %d, %u\n", reg[0], (signed) get_w(2), get_b(4));
- len = 5;
- break;
-
- case ICB: /* signed word, signed byte, unsigned byte */
- if (displ)
- zprintf(" %d, %d, %d\n", (signed) get_w(1), (signed char) get_b, get_b(4));
- len = 5;
- break;
-
- case BRV: /* unsigned length byte, register, zero or more registers */
- len = get_b(1); /* length byte = #opt. param. = #bytes - 2) */
- disp++; /* skip length */
- save_regs( reg, len );
- if (displ)
- {
- zprintf(".%d", len );
- for( int i = 0; i < len; i++ )
- zprintf("%s R%d", i ? "," : "", get_reg(i+1) );
- zprintf("\n");
- }
- len += 2;
- break;
-
- default:
- zprintf("t_inst: Invalid instruction format op=%02x\n", op );
- }
-
- if (flags & T_RUN) {
- if (displ) {
- /* dump the registers prior to execution */
- int i, j;
-
- for( i = 0; i < NUMREGS; i++ )
- {
- for( j = 0; j < i; j++ )
- if( reg[i] == reg[j] )
- reg[i] = NOTUSED;
- if( reg[i] != NOTUSED )
- prt_reg(reg[i]),
- before[i] = regs[reg[i]];
- }
- }
- /* execute the instruction */
- stat = interp(pc, retcode, 1);
-
- if (displ) {
- /* dump the registers after execution */
- int i;
- for( i = 0; i < NUMREGS; i++ )
- {
- if (reg[i] != NOTUSED )
- if( regs[reg[i]].disp != before[i].disp ||
- regs[reg[i]].page != before[i].page )
- zprintf("-->"), prt_reg(reg[i]);
- }
- }
- }
- else
- (*pc) += len;
- return stat;
- }
-
- /************************************************************************/
- /* Format a Series of Register Operands */
- /************************************************************************/
- void fmt_regs( int n )
- {
- if (displ) {
- for( int i = 1; i <= n; i++ )
- zprintf("%s R%d", i == 1 ? " " : ",", get_reg(i) );
- zprintf("\n");
- }
- }
-
- /************************************************************************/
- /* Save a Series of Register Operands */
- /************************************************************************/
- void save_regs( unsigned *reg, int n )
- {
- for( int i = 0; i < n && i < NUMREGS; i++ )
- reg[i] = get_reg(i+1);
- }
-
- /************************************************************************/
- /* Return Register Number */
- /************************************************************************/
- unsigned get_reg(unsigned offset)
- {
- return get_byte(page, disp + offset) >> 2;
- }
-
- /************************************************************************/
- /* Return Word Value */
- /************************************************************************/
- unsigned get_w(unsigned offset)
- {
- return get_word(page, disp + offset);
- }
-
- /************************************************************************/
- /* Return Byte Value */
- /************************************************************************/
- unsigned char get_b(unsigned offset)
- {
- return get_byte(page, disp + offset);
- }
-
- /************************************************************************/
- /* TIPC Scheme '84 Interactive Debugger */
- /* */
- /* Purpose: This utility assists the compiler developer by allowing */
- /* him or her to interactively display and modify the data */
- /* structures of the Scheme Virtual Machine as a program */
- /* executes. */
- /************************************************************************/
- RETVALUE sdebug( unsigned *retcode )
- {
- char buffer[BUFSIZE];
- unsigned disp;
- int i, j, k;
- unsigned length;
- unsigned page;
- unsigned sav_disp;
-
- if (!vm_debug)
- {
- reset:
- zprintf("\nAttempting to execute SCHEME-RESET\n"
- "[Returning to top level]\n");
- cb_reg.page = ADJPAGE(SPECCODE);
- cb_reg.disp = 0;
- s_pc = rst_ent - 1;
- goto run_it;
- }
-
- zprintf("\nPC Scheme Virtual Machine Debugger\n");
-
- for(;;)
- {
- zprintf("COMMAND: ");
- i = 0;
- ssetadr(ADJPAGE(IN_PAGE), IN_DISP);
- while ((j = take_ch()) != '\r')
- if (j != '\n')
- buffer[i++] = j;
- buffer[i] = take_ch(); /* get last zero */
- if( i == 0 )
- continue;
-
- switch (tolower(buffer[0]))
- {
- case 'a': /* display accounting information */
- accounting();
- break;
-
- case 'd': /* Dump Memory: Page:Offset [length] */
- i = tolower(buffer[1]); /* save second character */
- if (i != 'f')
- {
- unsigned idx = 1;
- if (check_page(buffer, &idx, &page, &disp))
- break;
- if ((length = hex_val(buffer, &idx)) == 0)
- length = DEFAULT_LENGTH;
- length = min(length, psize[page] - disp);
- }
- switch (i)
- {
- case 'g': /* dump global environment */
- page = CORRPAGE(gnv_reg.page);
- disp = gnv_reg.disp;
- while (page)
- {
- INTR_OUTPUT;
- zprintf("\n\t*** NEW RIB ***\n");
- sav_disp = disp;
- disp += 2 * sizeof(POINTER);
- for (i = 0; i < HT_SIZE; i++, disp += sizeof(POINTER))
- {
- INTR_OUTPUT;
- if ((j = get_byte(page, disp)) != 0)
- if( dump_environment(j, get_word(page, disp + 1)) )
- {
- page = sav_disp = 0;
- break;
- }
- }
- disp = get_word(page, sav_disp + 4);
- page = CORRPAGE(get_byte(page, sav_disp + 3));
- }
- break;
- case 'f': /* dump fluid environment */
- dump_environment(fnv_reg.page, fnv_reg.disp);
- break;
- case 'h': /* hexadecimal dump */
- dump_hex(page, disp, length);
- break;
- case 'p': /* dump the property list */
- dump_prop();
- break;
- case 's': /* dump the runtime stack */
- dump_stk();
- break;
- case 'o':
- dump_hash();
- break;
- default: /* regular ole dump of a page */
- dump_memory(page, disp, length);
- }
- break;
-
- case 'e': /* Execute this here program */
- { /* Note: breakpoints are dangerous !
- They are not relocated properly ! */
- unsigned idx = 1;
- char oldopcode;
- if (check_page(buffer, &idx, &page, &disp))
- break;
- if( page == 0 )
- goto run_it;
- oldopcode = get_byte( page, disp );
- put_byte( page, disp, 0xff ); /* write begin-debug */
- if( run(&s_pc, retcode, 0x7fff) == HALT )
- return HALT;
- put_byte( page, disp, oldopcode );
- if( CORRPAGE(cb_reg.page) == page && s_pc == disp+1 )
- s_pc--; /* back up to real instruction */
- if (!vm_debug)
- goto reset;
- break;
- }
-
- run_it:
- if (run(&s_pc, retcode, 0x7fff) == HALT)
- return HALT;
- else if (!vm_debug)
- goto reset;
- break;
-
- case 'g': /* invoke garbage collector */
- {
- unsigned after[NUMPAGES], before[NUMPAGES];
- unsigned idx = 1;
-
- sum_space(before);
- garbage();
- sum_space(after);
- for (i = DEDPAGES; i < NUMPAGES; i++)
- if( before[i] != after[i] )
- {
- zprintf("Page %3x: ", i );
- if( after[i] < before[i] )
- zprintf("%x bytes compacted\n", before[i] - after[i] );
- else zprintf("%x bytes recovered\n", after[i] - before[i] );
- }
-
- if( !hex_val(buffer, &idx) )
- break;
-
- for (i = DEDPAGES, j = 0; i < NUMPAGES; i++)
- if (ptype[i] == FREETYPE)
- j++;
- gcsquish(); /* go for memory compaction */
- for (i = DEDPAGES, k = 0; i < NUMPAGES; i++)
- if (ptype[i] == FREETYPE)
- k++;
- zprintf("%x pages reclaimed\n", k - j);
- break;
- }
- case '?': /* print out commands currently defined */
- zprintf("Valid Debugger Commands:\n"
- " A - display accounting information\n"
- " DH [page:offset [length]] - dump memory hex\n"
- " D [page:offset [length]] - dump memory formatted\n"
- " DF,DG,DS,DP - dump fluids, globals, stack, prop.list\n"
- " E [page:offset] - execute program (optional breakpoint)\n"
- " G - invoke Garbage collection\n"
- " I reg <CR> atom - input atom to register\n"
- " IP [n] - set IP to n; if none, decrement IP by 1\n"
- " O - display registers as s-expressions\n"
- " P - dump page table\n"
- " Q [retvalue] - quit (return to DOS)\n"
- " R,RE - display registers, do scheme-reset\n"
- " S - assembly debug\n"
- " T [n] - trace n instructions, 1 if no argument\n"
- " U - unassemble the next few instructions\n"
- " WB [page:offset data ...] - write bytes\n"
- " WW [page:offset data ...] - write words\n"
- " X [n] - execute n instructions, infinity if no argument\n"
- " ? - help (prints this information)\n");
- break;
-
- case 'i': /* input atom into register */
- if (tolower(buffer[1]) == 'p')
- {
- unsigned idx = 2;
- i = hex_val(buffer, &idx);
- s_pc = (i > 0 ? i : s_pc - 1);
- } else {
- unsigned idx = 1;
- i = int_val(buffer, &idx) % NUM_REGS;
- sread_atom(regs + i, ADJPAGE(IN_PAGE), IN_DISP);
- while ( take_ch() != '\r'); /* skip the rest of the line */
- take_ch(); /* get the last 0 */
- }
- break;
-
- case 'o': /* print s-expressions pointed by regs */
- {
- int i;
-
- for (i = 0; i < NUM_REGS; i++)
- if (regs[i].disp != UN_DISP || regs[i].page != ADJPAGE(UN_PAGE))
- sprint_reg(i, regs[i].page, regs[i].disp);
- }
- break;
-
- case 'p': /* print page table and page control information */
- dump_page_table();
- break;
-
- case 'q': /* quit */
- {
- unsigned idx = 1;
- *retcode = hex_val(buffer, &idx);
- return HALT;
- }
- case 'r':
- if (tolower(buffer[1]) == 'e')
- {
- cb_reg.page = ADJPAGE(SPECCODE);
- cb_reg.disp = 0;
- s_pc = rst_ent - 1;
- } else
- dump_regs(); /* dump registers */
- break;
-
- case 's': /* assembly debug */
- asm int 3
- break;
-
- case 't': /* trace instruction execution */
- {
- unsigned idx = 1, pc;
- RETVALUE stat;
-
- if( (length = hex_val(buffer, &idx)) == 0 )
- length = 1;
-
- while( length-- )
- if ((stat = t_inst(CORRPAGE(cb_reg.page), &s_pc, retcode, T_RUN | T_DISPLAY)) != PROCEED)
- break;
- if (stat == HALT)
- return HALT;
- pc = s_pc;
- t_inst(CORRPAGE(cb_reg.page), &pc, retcode, T_DISPLAY );
- }
- break;
-
- case 'u':
- dump_memory( CORRPAGE(cb_reg.page), s_pc, 32 );
- break;
-
- case 'w': /* write memory-- determine if byte or word */
- {
- unsigned idx = 2;
-
- if (check_page(buffer, &idx, &page, &disp))
- break;
- switch (tolower(buffer[1])) {
- case 'b': /* write byte */
- while ((i = hex_byte(buffer, &idx)) >= 0) {
- zprintf("%3x:%04x Previous contents: %02x Replaced by: %02x\n",
- page, disp,
- get_byte(page, disp), i);
- put_byte(page, disp, i);
- disp++;
- }
- break;
-
- case 'w': /* write word */
- {
- long i;
-
- while ((i = hex_word(buffer, &idx)) >= 0)
- {
- zprintf("%3x:%04x Previous contents: %04x Replaced by: %04lx\n",
- page, disp,
- get_word(page, disp), i);
- put_word(page, disp, i);
- disp += 2;
- }
- }
- break;
-
- default:
- goto bad_command;
- }
- }
- break;
-
- case 'x': /* instruction execution */
- {
- unsigned idx = 1;
- length = hex_val(buffer, &idx);
- }
- { /* volatile 'cause of use in case of register crash */
- RETVALUE stat;
- volatile unsigned done = (length ? length : 0xffff);
- volatile unsigned idx = 0;
- do {
- stat = interp(&s_pc, retcode, done );
- switch( stat )
- {
- case HALT:
- return HALT;
- case CLOBBERED:
- zprintf("\007Clobbered after %lx instructions\n",
- done - *retcode + ((long) idx) * 0xffff );
- case SDEBUG:
- length = 1; /* quit loop */
- break;
- case PROCEED:
- break;
- }
- idx++;
- } while( !length );
- }
- break;
-
- default:
- bad_command:
- zprintf("? unrecognized command\n");
- break;
- }
- }
- }
-
- /************************************************************************/
- /* extract a decimal value from a string */
- /************************************************************************/
- unsigned int_val(char str[], unsigned *idx)
- {
- char ch;
- unsigned ret_val = 0;
- int i;
-
- /* skip over any leading characters in string */
- while (str[*idx] != '\0' && !isdigit(str[*idx]))
- (*idx)++;
-
- /* continue to extract digits until end of string of delimiter */
- while ((ch = str[*idx]) != 0) {
- if ((i = get_int(ch)) >= 0)
- ret_val = (ret_val * 10) + i;
- else
- break;
- (*idx)++;
- }
- return ret_val;
- }
-
- /************************************************************************/
- /* extract a hexadecimal value from a string */
- /************************************************************************/
- unsigned hex_val(char str[], unsigned *idx)
- {
- char ch;
- unsigned ret_val = 0;
- int i;
-
- /* skip over any leading characters in string */
- while (str[*idx] != '\0' && !isxdigit(str[*idx]))
- (*idx)++;
-
- /* continue to extract digits until end of string of delimiter */
- while ((ch = str[*idx]) != 0) {
- if ((i = get_hex(ch)) >= 0)
- ret_val = (ret_val << 4) + i;
- else
- break;
- (*idx)++;
- }
- return ret_val;
- }
-
- /************************************************************************/
- /* Extract a byte value from a string */
- /************************************************************************/
- int hex_byte(char str[], unsigned *idx)
- {
- int first_digit, second_digit;
- while (str[*idx] == ' ')
- (*idx)++; /* skip leading blanks */
- if ((first_digit = get_hex(str[*idx])) < 0)
- return -1;
- (*idx)++;
- if ((second_digit = get_hex(str[*idx])) < 0)
- return first_digit;
- (*idx)++;
- return first_digit * 16 + second_digit;
- }
-
- /************************************************************************/
- /* Extract a word value from a string */
- /************************************************************************/
- long hex_word(char str[], unsigned *idx)
- {
- int digit, i;
- long ret_val = -1;
-
- while (str[*idx] == ' ')
- (*idx)++; /* skip leading blanks */
-
- for (i = 0; i < 4; i++) {
- if (str[*idx] == '\0')
- return ret_val;
- if ((digit = get_hex(str[*idx])) < 0)
- return ret_val;
- ret_val = (ret_val == -1 ? digit : (ret_val << 4) | digit);
- (*idx)++;
- }
- return ret_val;
- }
-
- /************************************************************************/
- /* Test for a hex digit-- if so, return its decimal value */
- /************************************************************************/
- int get_hex(char ch)
- {
- ch = toupper(ch);
-
- if( ch >= '0' && ch <= '9')
- return ch - '0';
- else if( ch >= 'A' && ch <= 'F')
- return ch + 10 - 'A';
- else return -1;
- }
-
- /************************************************************************/
- /* Test for a decimal digit-- if so, return its value */
- /************************************************************************/
- int get_int(char ch)
- {
- return isdigit(ch) ? ch - '0' : -1;
- }
-
- /************************************************************************/
- /* Verify page number, offset values */
- /* */
- /* Purpose: This routine checks the page number, displacement, and */
- /* length parameters keyed in by the interactive debug user */
- /* to make sure they are within acceptable bounds. */
- /************************************************************************/
- int check_page(char buffer[], unsigned *idx, unsigned *page, unsigned *disp)
- {
- int ret_val = -1;
-
- *page = hex_val(buffer, idx);
- *disp = hex_val(buffer, idx);
-
- /* Verify that page number is valid */
- if (*page == 0xffff || *page >= NUMPAGES) {
- zprintf("Error: Page numbers must be in the range 0 to %x\n",
- NUMPAGES - 1);
- } else {
- if (attrib[*page].FLAGS.nomemory) {
- zprintf("Error: Page 0x%x has not been allocated\n", *page);
- } else {
- if (*disp == 0xffff || *disp >= psize[*page])
- zprintf("Error: Displacements must be in the range 0x0000 to 0x%04x\n",
- psize[*page] - 1);
- else
- ret_val = 0; /* valid page, displacement, length */
- }
- }
- return ret_val;
- }
-
-
- /************************************************************************/
- /* Print s-expressive line of register contents to standard output */
- /************************************************************************/
- void sprint_reg(unsigned name, unsigned page, unsigned disp)
- {
- ssetadr(ADJPAGE(OUT_PAGE), OUT_DISP);
- zprintf("R%-2d: ", name );
- show = SP_OUTPUT | SP_SEPARE;
- sprint(CORRPAGE(page), disp, ADJPAGE(OUT_PAGE), OUT_DISP);
- zprintf("\n");
- }
-
- char *getsegment( int i, char *s )
- {
- int t = getbase(ADJPAGE(i));
- sprintf( s, t == 1 ? "EMMS" : "%04x", t );
- return s;
- }
-
- /************************************************************************/
- /* Format a dump of the Page Table */
- /************************************************************************/
- void dump_page_table(void)
- {
- unsigned i;
- unsigned start, end; /* starting and ending limits of FREE pages */
- unsigned space[NUMPAGES]; /* amount of free space in each page */
- char s[5];
-
- /* determine the amount of free space in each page */
- sum_space(space);
-
- /* Print Page Table Dump Headings */
- zprintf("\nDump of Scheme Memory Management Page Tables\n\n"
- "Page Page Base Next Link Free\n"
- " No Type Para Avail Page Size Bytes Attributes\n"
- "---- ---- ---- ----- ---- ---- ----- ----------\n");
- start = end = 0xffff;
- for (i = 0; i < nextpage; i++)
- {
- if( psize[i] == 0 )
- continue;
-
- if( ptype[i] == FREETYPE )
- {
- if( start == 0xffff )
- start = i;
- end = i;
- } else {
- INTR_OUTPUT;
- prt_free(&start, &end);
- zprintf("%4x %5s %s %4x %4x%c %4x %4x ", i,
- page_type[ptype[i] >> 1], getsegment(i,s), nextcell[i],
- pagelink[i], (i == pagelist[ptype[i] >> 1] ? '<' : ' '),
- psize[i], space[i]);
- /* print attributes for page */
- prt_atr(i);
-
- /* Flush line to output device */
- zprintf("\n");
- }
- }
- prt_free(&start, &end);
-
- /* Print summary of pages which are not allocated */
- if (nextpage < NUMPAGES) {
- if (nextpage == NUMPAGES - 1)
- zprintf("%4x is not allocated\n", nextpage);
- else
- zprintf("%4x-%x are not allocated\n", nextpage, NUMPAGES - 1);
- }
- }
-
- /************************************************************************/
- /* Print Page Attributes */
- /* */
- /* Purpose: This routine prints the attributes of a page on the */
- /* current print line. Attributes are separated by commas. */
- /************************************************************************/
- void prt_atr(unsigned page)
- {
- unsigned bits;
- static char *things[16] = {"atom", "list", "fixnum", "flonum", "bignum",
- "symbol", "string", "array", "no memory", "read only",
- "continuation", "closure", "inline code", "port", "code block", "char"};
- char *comma_needed = "";
- int i = 0;
-
- bits = attrib[page].word;
- while (bits) {
- if (bits & 0x8000) {
- zprintf("%s%s", comma_needed, things[i]);
- comma_needed = ",";
- }
- i++;
- bits = (bits << 1);
- }
- }
-
- /************************************************************************/
- /* Print Free (unused) Pages of Memory */
- /* */
- /* Purpose: Given a range of unused pages of memory, this routine */
- /* formats a message to indicate the presence of said pages. */
- /************************************************************************/
- void prt_free(unsigned *start, unsigned *end)
- {
- if( *start != 0xffff )
- {
- if( *start == *end )
- zprintf("Page %x is allocated, but unused\n", *start );
- else
- zprintf("Pages %x-%x are allocated, but unused\n", *start, *end );
- *start = *end = 0xffff;
- }
- }
-
- /************************************************************************
- * Output a scheme object (used by dump_scheme) *
- ************************************************************************/
- void printstring( char far *s, int len )
- {
- zprintf("\t\"");
-
- for( int i = 0; i < len; i++ )
- zprintf("%c%s", s[i] >= 32 && s[i] < 127 ? s[i] : '.',
- (i & 0x3f) == 0x3f && i < len-1 ? "\n\t" : "");
- zprintf("\"\n");
- }
-
- void output_flo( SCHEMEOBJ o, unsigned, unsigned, unsigned )
- {
- zprintf("FLONUM [%le]\n", o->flonum.data );
- }
-
- void output_str( SCHEMEOBJ o, unsigned, unsigned, unsigned )
- {
- int len = o->string.len - (o->string.buffer - (char far *) o);
- if( len < 0 )
- len += 6;
-
- zprintf("STRING.%04x [length %d]\n", o->string.len, len );
- printstring( o->string.buffer, len );
- }
-
- void output_sym( SCHEMEOBJ o, unsigned, unsigned, unsigned )
- {
- int len = o->symbol.len - (o->symbol.buffer - (char far *) o);
- if( len < 0 )
- len += 6;
-
- zprintf("SYMBOL.%04x [length %d, link %02x:%04x, hash %02x]\n", o->symbol.len, len,
- CORRPAGE(o->symbol.link.page), o->symbol.link.disp, o->symbol.hash );
- printstring( o->symbol.buffer, len );
- }
-
- void output_code( SCHEMEOBJ o, unsigned page, unsigned start, unsigned end )
- {
- unsigned entry = (int) o + o->codeblock.entry.disp;
- unsigned last = (int) o + o->codeblock.len;
-
- zprintf("CODE.%04x [begins at %x]\n", o->codeblock.len, entry );
-
- for( int i = 0; (int) &o->codeblock.constants[i] < entry; i++ )
- if( (int) &o->codeblock.constants[i] >= start &&
- (int) &o->codeblock.constants[i] < end )
- {
- INTR_OUTPUT;
- zprintf("\t%d:\t", i );
- annotate( CORRPAGE(o->codeblock.constants[i].page),
- o->codeblock.constants[i].disp );
- }
-
- while( entry < end && entry < last )
- {
- INTR_OUTPUT;
- t_inst( page, &entry, NULL, T_DISPLAY * (entry >= start) );
- }
- }
-
- void output_i86( SCHEMEOBJ o, unsigned page, unsigned start, unsigned end )
- {
- zprintf("INLINE.%04x\n", o->i86block.len );
-
- dump_hex( page, start, end );
- }
-
- void output_all( SCHEMEOBJ o, unsigned, unsigned start, unsigned end )
- {
- int i, next;
-
- zprintf("%s.%04x\n", page_type[o->vector.type >> 1], o->vector.len );
-
- if( end > (int) o + o->vector.len )
- end = (int) o + o->vector.len;
-
- for( i = 0; (int) &(o->vector.data[i]) < end; i = next )
- if( (int) &(o->vector.data[i]) >= start )
- {
- INTR_OUTPUT;
- /* see if following array entries are same as the current one */
- for( next = i+1; (int) &(o->vector.data[next]) < end; next++ )
- if( o->vector.data[i].page != o->vector.data[next].page ||
- o->vector.data[i].disp != o->vector.data[next].disp )
- break;
- if( next == i+1 )
- zprintf("#%d:\t", i );
- else zprintf("#%d-%d:\t", i, next );
-
- annotate( CORRPAGE(o->vector.data[i].page), o->vector.data[i].disp );
- }
- }
-
- void output_port( SCHEMEOBJ o, unsigned, unsigned, unsigned )
- {
- zprintf("PORT.%04x [In:", o->port.len );
- switch( o->port.flags & READ_MODE )
- {
- case READ_EXCLUSIVE:
- zprintf("exclusive"); break;
- case READ_SHARED:
- zprintf("shared"); break;
- case READ_PROTECTED:
- zprintf("protected"); break;
- case READ_CLOSED:
- zprintf("closed"); break;
- }
- zprintf(" Out:");
- switch( o->port.flags & WRITE_MODE )
- {
- case WRITE_EXCLUSIVE:
- zprintf("exclusive "); break;
- case WRITE_SHARED:
- zprintf("shared "); break;
- case WRITE_PROTECTED:
- zprintf("protected "); break;
- case WRITE_CLOSED:
- zprintf("closed "); break;
- }
- switch( o->port.flags & PORT_TYPE )
- {
- case TYPE_FILE:
- zprintf("File "); break;
- case TYPE_STRING:
- zprintf("String "); break;
- case TYPE_SOFTWARE:
- zprintf("Software "); break;
- case TYPE_WINDOW:
- zprintf("Window ");
- zprintf( (o->port.flags & PORT_WRAP) ? "Wrap " : "Clip ");
- if( o->port.flags & PORT_TRANSCRIPT ) zprintf("Transcript ");
- }
- if( (o->port.flags & PORT_TYPE) != TYPE_WINDOW )
- zprintf( (o->port.flags & PORT_BINARY) ? "Binary " : "Ascii ");
- if( o->port.flags & PORT_LOCKED )
- zprintf( "Locked ");
- zprintf( (o->port.flags & PORT_FLUSHED) ? "Flushed]\n" : "\b]\n");
-
- zprintf("\tSource at %2x:%04x\t", o->port.ptr.page, o->port.ptr.disp);
- show = SP_OUTPUT | SP_SEPARE;
- sprint(CORRPAGE(o->port.ptr.page), o->port.ptr.disp, ADJPAGE(OUT_PAGE), OUT_DISP);
- zprintf("\nCurrent position is line %d, column %d\n",
- o->port.curline, o->port.curcol);
-
- switch( o->port.flags & PORT_TYPE )
- {
- case TYPE_WINDOW:
- zprintf("\tWindow area: upper-left (%d,%d) size (%d,%d)\n",
- o->port.ulline, o->port.ulcol,
- o->port.nlines, o->port.ncols );
- zprintf("\tBorder attributes are %04x, Text attributes %04x\n", o->port.border, o->port.text );
- break;
- case TYPE_FILE:
- zprintf("\tFile handle %x, Buffer base offset %x\n",
- o->port.handle, o->port.chunk * BUFFSIZE );
- }
- zprintf("\tActive buffer:\n");
- printstring( o->port.buffer + o->port.bufpos,
- o->port.bufend - o->port.bufpos );
- }
-
- void output_big( SCHEMEOBJ o, unsigned, unsigned, unsigned )
- {
- int num = o->bignum.data.len/2 - (o->bignum.data.data - (unsigned far *) o);
-
- zprintf("BIGNUM.%04x %s\n\t", o->bignum.data.len, o->bignum.data.sign & 1 ? "Negative" : "Positive");
- for( int i = 0; i < num; i++ )
- zprintf("%04x%s", o->bignum.data.data[num-i-1], (i & 0xf) == 0xf && i < num-1 ? "\n\t" : "");
- zprintf("\n");
- }
-
- /************************************************************************/
- /* Produce a Formatted Dump of an Area of Scheme's Address Space */
- /************************************************************************/
- void dump_memory( unsigned page, unsigned disp, unsigned length )
- {
- char *description[NUMTYPES] =
- {"List Cells", "Fixnums", "Flonums",
- "Bignums", "Symbols", "Strings",
- "Arrays", "Continuation Cells",
- "Closures", "Nothing (unused)",
- "Code", "Inline Code", "Ports",
- "Characters", "Environments"};
-
- if (ptype[page] < NUMTYPES*2 && ptype[page] != FREETYPE) {
- zprintf("Page %x (attributes ", page ); prt_atr(page);
- zprintf(") contains %s\n", description[ptype[page] >> 1] );
-
- switch( ptype[page] )
- {
- case LISTTYPE:
- dump_list( page, disp, disp+length );
- break;
- case SYMTYPE:
- dump_scheme( page, disp, disp+length, 0, output_sym );
- break;
- case STRTYPE:
- dump_scheme( page, disp, disp+length, 0, output_str );
- break;
- case CODETYPE:
- dump_scheme( page, disp, disp+length, 0, output_code );
- break;
- case I86TYPE:
- dump_scheme( page, disp, disp+length, 0, output_i86 );
- break;
- case VECTTYPE:
- case CLOSTYPE:
- case CONTTYPE:
- case ENVTYPE:
- dump_scheme( page, disp, disp+length, 0, output_all );
- break;
- case FLOTYPE:
- dump_scheme( page, disp, disp+length, sizeof(FLONUM), output_flo );
- break;
- case PORTTYPE:
- dump_scheme( page, disp, disp+length, 0, output_port );
- break;
- case BIGTYPE:
- dump_scheme( page, disp, disp+length, 0, output_big );
- break;
- default:
- zprintf("Error: Invalid page type 0x%x\n", ptype[page] );
- }
- } else zprintf("Error: Invalid page type: 0x%x\n", ptype[page] );
- }
-
- /************************************************************************/
- /* Produce a Hex Dump of a Page of Scheme's Memory */
- /************************************************************************/
- void dump_hex( unsigned page, unsigned disp, unsigned length )
- {
- for( unsigned start = disp & 0xfff0; start <= disp + length; start++ )
- {
- INTR_OUTPUT;
- if( (start & 0xf) == 0 )
- zprintf("\n%2x:%04x ", page, start );
- if( start >= disp )
- zprintf("%02x ", get_byte(page, start) );
- else zprintf(" ");
- }
- zprintf("\n");
- }
-
- /************************************************************************/
- /* Produce Formatted Dump of a Page Containing List Cells */
- /************************************************************************/
- void dump_list( unsigned page, unsigned disp, unsigned end )
- {
- LIST far *l = &( scheme2c( page, 0 )->list );
- for( int count = 0; (int) (l+1) <= psize[page]; l++ )
- {
- if( l->car.page == 0xff )
- {
- count++;
- continue;
- }
- if( (int) (l+1) >= disp && (int) l < end )
- {
- INTR_OUTPUT;
-
- zprintf("%3x:%04x ( ", page, (int) l );
- if( l->car.page )
- zprintf("%2x:%04x . ", CORRPAGE(l->car.page), l->car.disp );
- else zprintf("NIL . ");
- if( l->cdr.page )
- zprintf("%2x:%04x )\n", CORRPAGE(l->cdr.page), l->cdr.disp );
- else zprintf("NIL )\n");
- }
- }
- zprintf("%x unused cells\n", count );
- }
-
- /************************************************************************/
- /* Produce Formatted Dump of a Page Containing Scheme Objects */
- /************************************************************************/
- void dump_scheme( unsigned page, unsigned start, unsigned end, unsigned size,
- void (*proc)( SCHEMEOBJ, unsigned, unsigned, unsigned ) )
- {
- int len, next;
-
- for( next = 0; next <= psize[page] - BLK_OVHD; next += len )
- {
- SCHEMEOBJ o = scheme2c(page,next);
-
- len = size ? size : o->_.len;
- if( len < 0 )
- len = 6;
-
- if( next+len > start && next < end )
- if( o->_.type != 0xff && (o->_.type & 0x3f) != FREETYPE )
- {
- zprintf("%3x:%04x ", page, next );
- (*proc)( scheme2c( page, next ), page, start, end );
- }
- }
- }
-
- /************************************************************************/
- /* Dump the runtime stack */
- /************************************************************************/
- void dump_stk(void)
- {
- STACKFRAME *fp;
- POINTER *tos;
-
- prt_reg(-4); /* print the value of prev_reg and the stack base */
- zprintf("BASE\t%04x\n", base );
-
- fp = (STACKFRAME *) (((char *) s_stack) + frameptr);
- tos = (POINTER *) (((char *) s_stack) + topofstack);
- while( tos > s_stack )
- {
- while( tos >= fp->data )
- {
- INTR_OUTPUT;
- zprintf("@%d:\t", tos - fp->data );
- annotate( CORRPAGE(tos->page), tos->disp );
- tos--;
- }
- zprintf("%4x: FRAME [cb=%x:%04x, ret=%04x, heap=%x:%04x slink=%04x, clos=%x:%04x]\n",
- base + &fp->codeblock - s_stack,
- CORRPAGE(fp->codeblock.page), fp->codeblock.disp, fp->ret.disp,
- CORRPAGE(fp->heap.page), fp->heap.disp,
- fp->slink.disp,
- CORRPAGE(fp->closure.page), fp->closure.disp );
-
- tos -= sizeof(STACKFRAME) / sizeof(POINTER) - 1;
- fp = (STACKFRAME *) (((char *) s_stack) + fp->dlink.disp - base);
- }
- }
-
- /************************************************************************/
- /* Dump the VM's Registers */
- /************************************************************************/
- void dump_regs(void)
- {
- int i;
- unsigned pc = s_pc;
-
- /* Print the Contents of the general purpose registers */
- for (i = 0; i < NUM_REGS; i++)
- if (regs[i].page != ADJPAGE(UN_PAGE) || regs[i].disp != UN_DISP)
- prt_reg(i);
-
- prt_reg(-1); /* print fnv */
- prt_reg(-3); /* print gnv */
- prt_reg(-2); /* print cb */
- if (tmp_reg.page & 1)
- zprintf("odd tmp_page\n");
- zprintf("tmp_reg ");
- annotate(CORRPAGE(tmp_reg.page), tmp_reg.disp);
- t_inst( CORRPAGE(cb_reg.page), &pc, NULL, T_DISPLAY );
- }
-
- void prt_reg( int reg )
- {
- REG r;
-
- /* print the register name and contents */
- switch( reg )
- {
- case -1:
- zprintf("FNV\t");
- r = fnv_reg;
- break;
- case -2:
- zprintf("CB\t");
- r = cb_reg;
- break;
- case -3:
- zprintf("GNV\t");
- r = gnv_reg;
- break;
- case -4:
- zprintf("PREV\t");
- r = prev_reg;
- break;
- default:
- zprintf("R%-2d\t", reg );
- r = regs[reg];
- }
-
- annotate(CORRPAGE(r.page), r.disp);
- }
-
- void commentstr( char sep, char far *buffer, int len )
- {
- if( len < 0 )
- len += 6;
- if( len > 30 )
- len = 30;
-
- zprintf(" %c", sep );
- while( len-- )
- zprintf("%c", *buffer++ );
- zprintf("%c\n", sep );
- }
-
- void annotate( unsigned page, unsigned disp )
- {
- SCHEMEOBJ o;
-
- zprintf("%2x:%04x\t%s", page, disp, page_type[CORRPAGE(ptype[page])] );
- o = scheme2c(page,disp);
-
- /* for values, show the value the register points to */
- switch( ptype[page] )
- {
- case SYMTYPE:
- commentstr('|', o->symbol.buffer, o->symbol.len - (o->symbol.buffer - (char far *) o) );
- break;
- case STRTYPE:
- commentstr('"', o->string.buffer, o->string.len - (o->string.buffer - (char far *) o) );
- break;
- case FIXTYPE:
- zprintf(" %d \n", disp );
- break;
- case FLOTYPE:
- zprintf(" %le\n", o->flonum.data );
- break;
- case CHARTYPE:
- for( int i = 0; i < SPECIALCHARS; i++ )
- {
- if( disp == *spchars[i] )
- {
- zprintf(" #\\%s\n", spchars[i]+1 );
- return;
- }
- }
- if( disp == 0 ) /* C++ bug: a '0' would end the display */
- disp = ' ';
-
- zprintf(" #\\%c\n", disp );
- break;
- case LISTTYPE:
- if( page == 0 )
- zprintf(" nil");
- default:
- zprintf("\n");
- }
- }
-
- /************************************************************************/
- /* Dump Environment */
- /************************************************************************/
- int dump_environment(unsigned page, unsigned disp)
- {
- REG search, pair, sym;
-
- for( search.page = page, search.disp = disp; search.page; take_cdr(&search) )
- {
- char *symbol;
-
- if( GETCHready() )
- {
- (void) GETCH();
- return 1; /* interrupted */
- }
-
- /* fetch pointer to symbol/value pair */
- pair = search;
- take_car(&pair);
-
- /* fetch pointer to symbol */
- sym = pair;
- take_car(&sym);
-
- symbol = symbol_name( CORRPAGE(sym.page), sym.disp );
- zprintf("%25s", symbol );
- rlsstr(symbol);
-
- /* display the value currently bound to the symbol */
- take_cdr( &pair );
- annotate( CORRPAGE(pair.page), pair.disp );
- ssetadr( ADJPAGE(OUT_PAGE), OUT_DISP );
- show = SP_OUTPUT | SP_SEPARE;
- sprint( CORRPAGE(pair.page), pair.disp, ADJPAGE(OUT_PAGE), OUT_DISP );
-
- zprintf("\n");
- }
- return 0; /* not interrupted */
- }
-
- /************************************************************************/
- /* Dump Contents of Property List */
- /************************************************************************/
- void dump_prop(void)
- {
- REG ent, prop, temp, sym, val;
- int hash_value; /* current hash key value */
- char *symbol; /* a symbol's print name */
-
- for (hash_value = 0; hash_value < HT_SIZE; hash_value++)
- {
- ent.page = prop_page[hash_value];
- ent.disp = prop_disp[hash_value];
- while (ent.page)
- {
- temp = ent;
- take_car(&temp);
- sym = temp;
- take_car(&sym);
- symbol = symbol_name(CORRPAGE(sym.page),sym.disp);
- zprintf("\nProperty List for |%s|\n", symbol);
- rlsstr(symbol);
-
- take_cdr(&temp);
- while(temp.page)
- {
- prop = temp;
- take_car(&prop);
- zprintf("\tproperty: ");
- annotate(CORRPAGE(prop.page), prop.disp);
- take_cdr(&temp);
- val = temp;
- take_car(&val);
- zprintf("\tvalue: ");
- annotate(CORRPAGE(val.page), val.disp);
- take_cdr(&temp);
- }
- take_cdr(&ent);
- }
- }
- }
-
- /************************************************************************/
- /* Dump Contents of Hash Table */
- /************************************************************************/
- extern POINTER obj_hlist;
-
- void dump_hash(void)
- {
- REG r = REG( obj_hlist );
-
- while( r.page )
- {
- REG s = r;
- take_car( &s );
- zprintf("\t[%d]\t", reg2c(&s)->list.cdr.disp );
- take_car( &s );
- annotate( CORRPAGE(s.page), s.disp );
- take_cdr( &r );
- }
- }
-
- #endif
-
- #ifdef VMDEBUG
- typedef struct {
- long val;
- char *name;
- } SORTELEM;
-
- int sortfunc( const void *a, const void *b )
- {
- unsigned long A = ((SORTELEM *) a)->val, B = ((SORTELEM *) b)->val;
- if( A > B )
- return -1;
- else return A < B;
- }
- #endif
-
- /************************************************************************/
- /* Display Accounting Information */
- /************************************************************************/
- void accounting(void)
- {
- extern int gc_count; /* garbage collector invocation count */
- extern long stk_in, stk_out;/* bytes transfered to/from the stack */
- #ifdef VMDEBUG
- int i;
- SORTELEM sorted[0x100];
- #endif
-
- zprintf("\nGarbage collector invoked %d times\n", gc_count);
-
- zprintf("%9ld bytes transferred from stack to heap\n"
- "%9ld bytes transferred from heap to stack\n", stk_out, stk_in );
-
- #ifdef VMDEBUG
- for( i = 0; i < 0x100; i++ )
- sorted[i].val = icount[i], sorted[i].name = opcodes[i];
-
- qsort( sorted, 0x100, sizeof(sorted[0]), sortfunc );
- for( i = 0; i < 0x100 && sorted[i].val; i++ )
- {
- zprintf("%15s:%-9ld", sorted[i].name, sorted[i].val );
- if( i % 3 == 3-1 )
- zprintf("\n");
- if( i % 30 == 30-1 )
- {
- zprintf("[ \\nq]\r");
- if( (GETCH() | ('a' - 'A')) == 'q')
- break;
- }
- }
- zprintf("\n");
- #endif
- }